{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "# pandas analysis\n",
    "# 数据聚合和分组操作\n",
    "\n",
    "import numpy as np\n",
    "import pandas as pd\n",
    "import matplotlib.pyplot as plt\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 对数据集进行分组并对各组应用一个函数（无论是聚合还是转换） ， 通常是数据分析工作中的重要环节\n",
    "#   在将数据集加载、 融合、 准备好之后， 通常就是计算分组统计或生成透视表。 \n",
    "# pandas 提供# 了一个灵活高效的 gruopby 功能，能以一种自然的方式对数据集进行切片 切块 摘要等操作。\n",
    "\n",
    "# 关系型数据库 和 SQL（Structured Query Language， 结构化查询语言） \n",
    "#    能够如此流行的原因之一就是其能够方便地对数据进行连接、过滤、转换和聚合\n",
    "# 但是， 像 SQL 这样的查询语言所能执行的分组运算的种类很有限\n",
    "# 由于 Python 和 pandas 强大的表达能力，可以执行复杂得多的分组运算（利用任何可以接受pandas对象或NumPy数组的函数） 。 在本章中， 你\n",
    "#     1、使用一个或多个键（形式可以是函数、 数组或DataFrame列名） 分割pandas对象\n",
    "#     2、计算分组的概述统计， 比如数量、 平均值或标准差， 或是用户定义的函数\n",
    "#     3、应用组内转换或其他运算， 如规格化、 线性回归、 排名或选取子集等\n",
    "#     4、计算透视表或交叉表\n",
    "#     5、执行分位数分析以及其它统计分组分析\n",
    "#     6、对时间序列数据的聚合（groupby的特殊用法之一） 也称作重采样（resampling）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Groupby 机制\n",
    "\n",
    "# Hadley Wickham（许多热门R语言包的作者） 创造了一个用于表示分组运算的术语\n",
    "#       \"split-applycombine\"（拆分－应用－合并） \n",
    "#   第一个阶段， pandas 对象（无论是 Series、 DataFrame 还是其他的）中的数据\n",
    "#              会根据你所提供的一个或多个键被拆分（split） 为多组\n",
    "#             拆分操作是在对象的特定轴上执行的\n",
    "#             DataFrame 可以在其行（axis=0） 或列（axis=1） 上进行分组\n",
    "#   然后，将一个函数应用（apply） 到各个分组并产生一个新值\n",
    "#   最后， 所有这些函数的执行结果会被合并（combine） 到最终的结果对象中\n",
    "# 结果对象的形式一般取决于数据上所执行的操作\n",
    "\n",
    "# 如下图所示"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "![self](./../image/groupby.png)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>key1</th>\n",
       "      <th>key2</th>\n",
       "      <th>data1</th>\n",
       "      <th>data2</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>a</td>\n",
       "      <td>one</td>\n",
       "      <td>0.085855</td>\n",
       "      <td>-2.622739</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>a</td>\n",
       "      <td>two</td>\n",
       "      <td>0.101006</td>\n",
       "      <td>2.430120</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>b</td>\n",
       "      <td>one</td>\n",
       "      <td>0.850283</td>\n",
       "      <td>0.551016</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>b</td>\n",
       "      <td>two</td>\n",
       "      <td>0.089985</td>\n",
       "      <td>-0.892486</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>a</td>\n",
       "      <td>one</td>\n",
       "      <td>1.277483</td>\n",
       "      <td>0.304751</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "  key1 key2     data1     data2\n",
       "0    a  one  0.085855 -2.622739\n",
       "1    a  two  0.101006  2.430120\n",
       "2    b  one  0.850283  0.551016\n",
       "3    b  two  0.089985 -0.892486\n",
       "4    a  one  1.277483  0.304751"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 分组键可以有多种形式， 且类型不必相同：\n",
    "#    - 列表或数组， 其长度与待分组的轴一样。\n",
    "#    - 表示DataFrame某个列名的值。\n",
    "#    - 字典或Series， 给出待分组轴上的值与分组名之间的对应关系。\n",
    "#    - 函数， 用于处理轴索引或索引中的各个标签。\n",
    "\n",
    "# 注意， 后三种都只是快捷方式而已， 其最终目的仍然是产生一组用于拆分对象的值。 \n",
    "\n",
    "# 一个简单的表格型数据集（以DataFrame的形式）\n",
    "df = pd.DataFrame({'key1' : ['a', 'a', 'b', 'b', 'a'],\n",
    "                   'key2' : ['one', 'two', 'one', 'two', 'one'],\n",
    "                   'data1' : np.random.randn(5),\n",
    "                   'data2' : np.random.randn(5)})\n",
    "df"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<pandas.core.groupby.generic.SeriesGroupBy object at 0x00000000091BF248>"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 假设想要按照 key1 进行分组，并计算 data1 的平均值\n",
    "# 实现方式：访问 data1 ，并根据 key1 调用 groupby\n",
    "grouped = df['data1'].groupby(df['key1'])\n",
    "grouped"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "pandas.core.groupby.generic.SeriesGroupBy"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "type(grouped)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "key1\n",
       "a    0.488115\n",
       "b    0.470134\n",
       "Name: data1, dtype: float64"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 变量 grouped 是一个 GroupBy 对象，实际并未进行任何计算，只是含有有关分组键 df['key1'] 的中间数据\n",
    "# 简单来说，就是该对象已经有了对各组分组执行运算所需的一切信息\n",
    "# 调用 GroupBy 的 mean 方法来计算分组平均值\n",
    "grouped.mean()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "key1  key2\n",
       "a     one     0.681669\n",
       "      two     0.101006\n",
       "b     one     0.850283\n",
       "      two     0.089985\n",
       "Name: data1, dtype: float64"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 详细讲解 .mean()的调用过程\n",
    "# 这里最重要的是， 数据（Series） 根据分组键进行了聚合， 产生了一个新的 Series，\n",
    "# 其索引为 key1 列中的唯一值, 之所以结果中索引的名称为 key1，是因为原始 DataFrame 的列 df['key1'] 就叫这个名字\n",
    "\n",
    "# 如果一次传入多个数组的列表，也就是通过多个键进行分组，得到的 Series 是一个层次化索引\n",
    "means = df['data1'].groupby([df['key1'], df['key2']]).mean()\n",
    "means"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th>key2</th>\n",
       "      <th>one</th>\n",
       "      <th>two</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>key1</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>a</th>\n",
       "      <td>0.681669</td>\n",
       "      <td>0.101006</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>b</th>\n",
       "      <td>0.850283</td>\n",
       "      <td>0.089985</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "key2       one       two\n",
       "key1                    \n",
       "a     0.681669  0.101006\n",
       "b     0.850283  0.089985"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "means.unstack()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "California  2005    0.101006\n",
       "            2006    0.850283\n",
       "Ohio        2005    0.087920\n",
       "            2006    1.277483\n",
       "Name: data1, dtype: float64"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 在这个例子中， 分组键均为 Series\n",
    "#  实际上， 分组键可以是任何长度适当的数组：\n",
    "states = np.array(['Ohio', 'California', 'California', 'Ohio', 'Ohio'])\n",
    "years = np.array([2005, 2005, 2006, 2005, 2006])\n",
    "df['data1'].groupby([states, years]).mean()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>data1</th>\n",
       "      <th>data2</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>key1</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>a</th>\n",
       "      <td>0.488115</td>\n",
       "      <td>0.037377</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>b</th>\n",
       "      <td>0.470134</td>\n",
       "      <td>-0.170735</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "         data1     data2\n",
       "key1                    \n",
       "a     0.488115  0.037377\n",
       "b     0.470134 -0.170735"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 通常，分组信息就位于相同的要处理 DataFrame中\n",
    "# 还可以将列名（可以是字符串、 数字 或其他Python对象） 用作分组键\n",
    "df.groupby('key1').mean()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th>data1</th>\n",
       "      <th>data2</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>key1</th>\n",
       "      <th>key2</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th rowspan=\"2\" valign=\"top\">a</th>\n",
       "      <th>one</th>\n",
       "      <td>0.681669</td>\n",
       "      <td>-1.158994</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>two</th>\n",
       "      <td>0.101006</td>\n",
       "      <td>2.430120</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th rowspan=\"2\" valign=\"top\">b</th>\n",
       "      <th>one</th>\n",
       "      <td>0.850283</td>\n",
       "      <td>0.551016</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>two</th>\n",
       "      <td>0.089985</td>\n",
       "      <td>-0.892486</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "              data1     data2\n",
       "key1 key2                    \n",
       "a    one   0.681669 -1.158994\n",
       "     two   0.101006  2.430120\n",
       "b    one   0.850283  0.551016\n",
       "     two   0.089985 -0.892486"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df.groupby(['key1', 'key2']).mean()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "key1  key2\n",
       "a     one     2\n",
       "      two     1\n",
       "b     one     1\n",
       "      two     1\n",
       "dtype: int64"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 可能已经注意到了， 第一个例子在执行 df.groupby('key1').mean() 时，\n",
    "#    结果中没有 key2 列, 这是因为 df['key2'] 不是数值数据（俗称“麻烦列”），所以被从结果中排除了\n",
    "# 默认情况下， 所有数值列都会被聚合，虽然有时可能会被过滤为一个子集\n",
    "\n",
    "# noting: 任何分组关键词中的缺失值，都会被从结果中除去\n",
    "\n",
    "# 无论准备拿 groupby 做什么，都有可能会用到 GroupBy 的 size 方法，可以返回一个含有分组大小的 Series：\n",
    "df.groupby(['key1', 'key2']).size()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "a\n",
      "  key1 key2     data1     data2\n",
      "0    a  one  0.085855 -2.622739\n",
      "1    a  two  0.101006  2.430120\n",
      "4    a  one  1.277483  0.304751\n",
      "b\n",
      "  key1 key2     data1     data2\n",
      "2    b  one  0.850283  0.551016\n",
      "3    b  two  0.089985 -0.892486\n"
     ]
    }
   ],
   "source": [
    "# 对分组进行迭代\n",
    "\n",
    "# GroupBy 对象支持迭代，可以产生一组二元元组（有分组名和数据块组成）\n",
    "for name, group in df.groupby('key1'):\n",
    "    print(name)\n",
    "    print(group)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "('a', 'one')\n",
      "  key1 key2     data1     data2\n",
      "0    a  one  0.085855 -2.622739\n",
      "4    a  one  1.277483  0.304751\n",
      "('a', 'two')\n",
      "  key1 key2     data1    data2\n",
      "1    a  two  0.101006  2.43012\n",
      "('b', 'one')\n",
      "  key1 key2     data1     data2\n",
      "2    b  one  0.850283  0.551016\n",
      "('b', 'two')\n",
      "  key1 key2     data1     data2\n",
      "3    b  two  0.089985 -0.892486\n"
     ]
    }
   ],
   "source": [
    "# 对于多重键的情况， 元组的第一个元素将会是由键值组成的元组：\n",
    "for (k1, k2), group in df.groupby(['key1', 'key2']):\n",
    "    print((k1, k2))\n",
    "    print(group)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'a':   key1 key2     data1     data2\n",
       " 0    a  one  0.085855 -2.622739\n",
       " 1    a  two  0.101006  2.430120\n",
       " 4    a  one  1.277483  0.304751,\n",
       " 'b':   key1 key2     data1     data2\n",
       " 2    b  one  0.850283  0.551016\n",
       " 3    b  two  0.089985 -0.892486}"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 当然，可以对这些数据片段做任何操作\n",
    "# 有一个可能会觉得有用的运算： 将这些数据片段做成一个字典：\n",
    "pieces = dict(list(df.groupby('key1')))\n",
    "pieces"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>key1</th>\n",
       "      <th>key2</th>\n",
       "      <th>data1</th>\n",
       "      <th>data2</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>b</td>\n",
       "      <td>one</td>\n",
       "      <td>0.850283</td>\n",
       "      <td>0.551016</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>b</td>\n",
       "      <td>two</td>\n",
       "      <td>0.089985</td>\n",
       "      <td>-0.892486</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "  key1 key2     data1     data2\n",
       "2    b  one  0.850283  0.551016\n",
       "3    b  two  0.089985 -0.892486"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "pieces['b']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "key1      object\n",
       "key2      object\n",
       "data1    float64\n",
       "data2    float64\n",
       "dtype: object"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# groupby 默认是在 axis=0 （行）进行分组的， 通过设置也可以在其他任何轴上进行分组\n",
    "# 拿上面例子中的 df 来说，可以根据 dtype 对列进行分组：\n",
    "df.dtypes"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "float64\n",
      "      data1     data2\n",
      "0  0.085855 -2.622739\n",
      "1  0.101006  2.430120\n",
      "2  0.850283  0.551016\n",
      "3  0.089985 -0.892486\n",
      "4  1.277483  0.304751\n",
      "object\n",
      "  key1 key2\n",
      "0    a  one\n",
      "1    a  two\n",
      "2    b  one\n",
      "3    b  two\n",
      "4    a  one\n"
     ]
    }
   ],
   "source": [
    "grouped = df.groupby(df.dtypes, axis=1)\n",
    "\n",
    "for dtype, group in grouped:\n",
    "    print(dtype)\n",
    "    print(group)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 由于可能不太熟悉书中使用的一些有关编程和数据科学方面的常用术语， 所以在这里先给出其简单定义：\n",
    "#     1、数据规整（Munge/Munging/Wrangling） 指的是将非结构化和（或） 散乱数据处理为结构化或整\n",
    "#          洁形式的整个过程。 这几个词已经悄悄成为当今数据黑客们的行话了。 Munge这个词跟Lunge押韵。\n",
    "#     2、伪码（Pseudocode） 算法或过程的“代码式”描述， 而这些代码本身并不是实际有效的源代码。\n",
    "#     3、语法糖（Syntactic sugar） 这是一种编程语法， 它并不会带来新的特性， 但却能使代码更易读、更易写。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 选取一列或列的子集\n",
    "\n",
    "# 对于由 DataFrame 产生的 GroupBy 对象， \n",
    "#  如果用一个（单个字符串）或一组（字符串数组）列名对其进行索引，就能实现选取部分列进行聚合的目的。 \n",
    "#  也就是说：\n",
    "# df.groupby('key1')['data1']\n",
    "# df.groupby('key1')[['data2']]\n",
    "\n",
    "# 代码的语法糖：也就是从 Python 语法角度说应该是下面代码，从代码可读性和可理解性应该是上面代码\n",
    "\n",
    "# df['data1'].groupby(df['key1'])\n",
    "# df[['data2']].groupby(df['key1'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th>data2</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>key1</th>\n",
       "      <th>key2</th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th rowspan=\"2\" valign=\"top\">a</th>\n",
       "      <th>one</th>\n",
       "      <td>-1.158994</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>two</th>\n",
       "      <td>2.430120</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th rowspan=\"2\" valign=\"top\">b</th>\n",
       "      <th>one</th>\n",
       "      <td>0.551016</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>two</th>\n",
       "      <td>-0.892486</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "              data2\n",
       "key1 key2          \n",
       "a    one  -1.158994\n",
       "     two   2.430120\n",
       "b    one   0.551016\n",
       "     two  -0.892486"
      ]
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 尤其对于大数据集，很可能只需要对部分列进行聚合\n",
    "#  例如，在前面那个数据集中，如果只需计算 data2 列的平均值并以 DataFrame 形式得到结果\n",
    "df.groupby(['key1', 'key2'])[['data2']].mean()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<pandas.core.groupby.generic.SeriesGroupBy object at 0x000000000569D8C8>"
      ]
     },
     "execution_count": 28,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 这种索引操作所返回的对象是一个已分组的 DataFrame（如果传入的是列表或数组） \n",
    "#          或已分组的 Series（如果传入的是标量形式的单个列名） ：\n",
    "s_grouped = df.groupby(['key1', 'key2'])['data2']\n",
    "s_grouped"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "key1  key2\n",
       "a     one    -1.158994\n",
       "      two     2.430120\n",
       "b     one     0.551016\n",
       "      two    -0.892486\n",
       "Name: data2, dtype: float64"
      ]
     },
     "execution_count": 29,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "s_grouped.mean()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>a</th>\n",
       "      <th>b</th>\n",
       "      <th>c</th>\n",
       "      <th>d</th>\n",
       "      <th>e</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>Joe</th>\n",
       "      <td>2.315610</td>\n",
       "      <td>-0.165255</td>\n",
       "      <td>-1.052396</td>\n",
       "      <td>0.709598</td>\n",
       "      <td>0.543279</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Steve</th>\n",
       "      <td>1.814661</td>\n",
       "      <td>-0.788101</td>\n",
       "      <td>-1.117939</td>\n",
       "      <td>-1.852481</td>\n",
       "      <td>-1.620563</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Wes</th>\n",
       "      <td>0.065038</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>-1.234193</td>\n",
       "      <td>1.250431</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Jim</th>\n",
       "      <td>-1.494505</td>\n",
       "      <td>-0.687324</td>\n",
       "      <td>2.593953</td>\n",
       "      <td>0.469832</td>\n",
       "      <td>1.585922</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Travis</th>\n",
       "      <td>-0.059679</td>\n",
       "      <td>1.422576</td>\n",
       "      <td>-0.143448</td>\n",
       "      <td>1.052608</td>\n",
       "      <td>-1.078617</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "               a         b         c         d         e\n",
       "Joe     2.315610 -0.165255 -1.052396  0.709598  0.543279\n",
       "Steve   1.814661 -0.788101 -1.117939 -1.852481 -1.620563\n",
       "Wes     0.065038       NaN       NaN -1.234193  1.250431\n",
       "Jim    -1.494505 -0.687324  2.593953  0.469832  1.585922\n",
       "Travis -0.059679  1.422576 -0.143448  1.052608 -1.078617"
      ]
     },
     "execution_count": 30,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 通过 字典 或 Series 进行分组\n",
    "# 除数组以外， 分组信息还可以其他形式存在\n",
    "\n",
    "people = pd.DataFrame(np.random.randn(5, 5),\n",
    "                      columns=['a', 'b', 'c', 'd', 'e'],\n",
    "                      index=['Joe', 'Steve', 'Wes', 'Jim', 'Travis'])\n",
    "\n",
    "people.iloc[2:3, [1, 2]] = np.nan\n",
    "people"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>blue</th>\n",
       "      <th>red</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>Joe</th>\n",
       "      <td>-0.342798</td>\n",
       "      <td>2.693634</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Steve</th>\n",
       "      <td>-2.970419</td>\n",
       "      <td>-0.594003</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Wes</th>\n",
       "      <td>-1.234193</td>\n",
       "      <td>1.315469</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Jim</th>\n",
       "      <td>3.063784</td>\n",
       "      <td>-0.595907</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Travis</th>\n",
       "      <td>0.909160</td>\n",
       "      <td>0.284279</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "            blue       red\n",
       "Joe    -0.342798  2.693634\n",
       "Steve  -2.970419 -0.594003\n",
       "Wes    -1.234193  1.315469\n",
       "Jim     3.063784 -0.595907\n",
       "Travis  0.909160  0.284279"
      ]
     },
     "execution_count": 31,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 现在， 假设已知列的分组关系，并希望根据分组计算列的和：\n",
    "mapping = {'a': 'red', 'b': 'red', 'c': 'blue',\n",
    "           'd': 'blue', 'e': 'red', 'f' : 'orange'}\n",
    "\n",
    "# 现在，可以将这个字典传给 groupby，来构造数组，\n",
    "# 可以直接传递字典（包含了键 “f” 来强调， 存在未使用的分组键是可以的） ：\n",
    "by_column = people.groupby(mapping, axis=1)\n",
    "by_column.sum()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "a       red\n",
       "b       red\n",
       "c      blue\n",
       "d      blue\n",
       "e       red\n",
       "f    orange\n",
       "dtype: object"
      ]
     },
     "execution_count": 32,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "map_series = pd.Series(mapping)\n",
    "map_series"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>blue</th>\n",
       "      <th>red</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>Joe</th>\n",
       "      <td>2</td>\n",
       "      <td>3</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Steve</th>\n",
       "      <td>2</td>\n",
       "      <td>3</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Wes</th>\n",
       "      <td>1</td>\n",
       "      <td>2</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Jim</th>\n",
       "      <td>2</td>\n",
       "      <td>3</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Travis</th>\n",
       "      <td>2</td>\n",
       "      <td>3</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "        blue  red\n",
       "Joe        2    3\n",
       "Steve      2    3\n",
       "Wes        1    2\n",
       "Jim        2    3\n",
       "Travis     2    3"
      ]
     },
     "execution_count": 33,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "people.groupby(map_series, axis=1).count()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>a</th>\n",
       "      <th>b</th>\n",
       "      <th>c</th>\n",
       "      <th>d</th>\n",
       "      <th>e</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>0.886143</td>\n",
       "      <td>-0.852580</td>\n",
       "      <td>1.541557</td>\n",
       "      <td>-0.054764</td>\n",
       "      <td>3.379632</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>1.814661</td>\n",
       "      <td>-0.788101</td>\n",
       "      <td>-1.117939</td>\n",
       "      <td>-1.852481</td>\n",
       "      <td>-1.620563</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>-0.059679</td>\n",
       "      <td>1.422576</td>\n",
       "      <td>-0.143448</td>\n",
       "      <td>1.052608</td>\n",
       "      <td>-1.078617</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "          a         b         c         d         e\n",
       "3  0.886143 -0.852580  1.541557 -0.054764  3.379632\n",
       "5  1.814661 -0.788101 -1.117939 -1.852481 -1.620563\n",
       "6 -0.059679  1.422576 -0.143448  1.052608 -1.078617"
      ]
     },
     "execution_count": 34,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 通过函数进行分组\n",
    "\n",
    "# 比起使用字典或 Series，使用 Python 函数是一种更原生的方法定义分组映射\n",
    "#  任何被当做分组键的函数都会在各个索引值上被调用一次，其返回值就会被用作分组名称\n",
    "\n",
    "#  具体点说，以上一小节的示例 DataFrame 为例，其索引值为人的名字\n",
    "# 可以计算一个字符串长度的数组，更简单的方法是传入 len 函数\n",
    "people.groupby(len).sum()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th>a</th>\n",
       "      <th>b</th>\n",
       "      <th>c</th>\n",
       "      <th>d</th>\n",
       "      <th>e</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th rowspan=\"2\" valign=\"top\">3</th>\n",
       "      <th>one</th>\n",
       "      <td>0.065038</td>\n",
       "      <td>-0.165255</td>\n",
       "      <td>-1.052396</td>\n",
       "      <td>-1.234193</td>\n",
       "      <td>0.543279</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>two</th>\n",
       "      <td>-1.494505</td>\n",
       "      <td>-0.687324</td>\n",
       "      <td>2.593953</td>\n",
       "      <td>0.469832</td>\n",
       "      <td>1.585922</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <th>one</th>\n",
       "      <td>1.814661</td>\n",
       "      <td>-0.788101</td>\n",
       "      <td>-1.117939</td>\n",
       "      <td>-1.852481</td>\n",
       "      <td>-1.620563</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <th>two</th>\n",
       "      <td>-0.059679</td>\n",
       "      <td>1.422576</td>\n",
       "      <td>-0.143448</td>\n",
       "      <td>1.052608</td>\n",
       "      <td>-1.078617</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "              a         b         c         d         e\n",
       "3 one  0.065038 -0.165255 -1.052396 -1.234193  0.543279\n",
       "  two -1.494505 -0.687324  2.593953  0.469832  1.585922\n",
       "5 one  1.814661 -0.788101 -1.117939 -1.852481 -1.620563\n",
       "6 two -0.059679  1.422576 -0.143448  1.052608 -1.078617"
      ]
     },
     "execution_count": 35,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 将函数跟数组、列表、字典、Series 混合使用也不是问题，因为任何东西在内部都会被转换为数组\n",
    "key_list = ['one', 'one', 'one', 'two', 'two']\n",
    "people.groupby([len, key_list]).min()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead tr th {\n",
       "        text-align: left;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr>\n",
       "      <th>cty</th>\n",
       "      <th colspan=\"3\" halign=\"left\">US</th>\n",
       "      <th colspan=\"2\" halign=\"left\">JP</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>tenor</th>\n",
       "      <th>1</th>\n",
       "      <th>3</th>\n",
       "      <th>5</th>\n",
       "      <th>1</th>\n",
       "      <th>3</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>0.245885</td>\n",
       "      <td>-0.329153</td>\n",
       "      <td>0.092811</td>\n",
       "      <td>1.037349</td>\n",
       "      <td>1.482598</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>-1.812302</td>\n",
       "      <td>-0.270322</td>\n",
       "      <td>0.319838</td>\n",
       "      <td>1.524951</td>\n",
       "      <td>-0.912206</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>1.447077</td>\n",
       "      <td>0.767615</td>\n",
       "      <td>2.547866</td>\n",
       "      <td>0.639822</td>\n",
       "      <td>-0.085907</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>-0.521469</td>\n",
       "      <td>2.705246</td>\n",
       "      <td>-1.185670</td>\n",
       "      <td>-1.297573</td>\n",
       "      <td>-0.212007</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "cty          US                            JP          \n",
       "tenor         1         3         5         1         3\n",
       "0      0.245885 -0.329153  0.092811  1.037349  1.482598\n",
       "1     -1.812302 -0.270322  0.319838  1.524951 -0.912206\n",
       "2      1.447077  0.767615  2.547866  0.639822 -0.085907\n",
       "3     -0.521469  2.705246 -1.185670 -1.297573 -0.212007"
      ]
     },
     "execution_count": 36,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 根据索引级别分组\n",
    "\n",
    "# 层次化索引数据集最方便的地方就在于它能够根据轴索引的一个级别进行聚合：\n",
    "columns = pd.MultiIndex.from_arrays([['US', 'US', 'US', 'JP', 'JP'],\n",
    "                                     [1, 3, 5, 1, 3]],\n",
    "                                     names=['cty', 'tenor'])\n",
    "\n",
    "hier_df = pd.DataFrame(np.random.randn(4, 5), columns=columns)\n",
    "hier_df"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th>cty</th>\n",
       "      <th>JP</th>\n",
       "      <th>US</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>2</td>\n",
       "      <td>3</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>2</td>\n",
       "      <td>3</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>2</td>\n",
       "      <td>3</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>2</td>\n",
       "      <td>3</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "cty  JP  US\n",
       "0     2   3\n",
       "1     2   3\n",
       "2     2   3\n",
       "3     2   3"
      ]
     },
     "execution_count": 37,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 要根据级别分组， 使用level关键字传递级别序号或名字：\n",
    "hier_df.groupby(level='cty', axis=1).count()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>key1</th>\n",
       "      <th>key2</th>\n",
       "      <th>data1</th>\n",
       "      <th>data2</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>a</td>\n",
       "      <td>one</td>\n",
       "      <td>0.085855</td>\n",
       "      <td>-2.622739</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>a</td>\n",
       "      <td>two</td>\n",
       "      <td>0.101006</td>\n",
       "      <td>2.430120</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>b</td>\n",
       "      <td>one</td>\n",
       "      <td>0.850283</td>\n",
       "      <td>0.551016</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>b</td>\n",
       "      <td>two</td>\n",
       "      <td>0.089985</td>\n",
       "      <td>-0.892486</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>a</td>\n",
       "      <td>one</td>\n",
       "      <td>1.277483</td>\n",
       "      <td>0.304751</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "  key1 key2     data1     data2\n",
       "0    a  one  0.085855 -2.622739\n",
       "1    a  two  0.101006  2.430120\n",
       "2    b  one  0.850283  0.551016\n",
       "3    b  two  0.089985 -0.892486\n",
       "4    a  one  1.277483  0.304751"
      ]
     },
     "execution_count": 39,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 数据聚合\n",
    "\n",
    "# 聚合指的是任何能够从数组产生标量值的数据转换过程\n",
    "#  比如 mean、count、min 以及 sum 等\n",
    "\n",
    "# 可能想知道在 GroupBy 对象上调用 mean() 时究竟发生了什么\n",
    "#  许多常见的聚合运算都有进行优化。 然而， 除了这些方法，还可以使用其它的\n",
    "\n",
    "# 函数名        说明\n",
    "# count         分组中非NA值的数量\n",
    "# sum           非 NA 值的和\n",
    "# mean          非 NA 值的平均值\n",
    "# median        非 NA 值的算术中位数\n",
    "# std. var      无偏(分母为n-1)标准差和方差\n",
    "# min、max      非 NA 值的最小值和最大值\n",
    "# prod          非 NA 值的积\n",
    "# first、last   第一个和最后一个非NA值\n",
    "\n",
    "# 可以使用自己发明的聚合运算， 还可以调用分组对象上已经定义好的任何方法\n",
    "#    例如， quantile 可以计算 Series 或 DataFrame 列 的样本分位数。\n",
    "# 虽然 quantile 并没有明确地实现于 GroupBy， 但它是一个 Series 方法， 所以这里是能用的\n",
    "# 实际上， GroupBy 会高效地对 Series 进行切片，然后对各片调用 piece.quantile(0.9)，最后将这些结果组装成最终结果\n",
    "df"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "key1\n",
       "a    1.042188\n",
       "b    0.774253\n",
       "Name: data1, dtype: float64"
      ]
     },
     "execution_count": 40,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "grouped = df.groupby('key1')\n",
    "grouped['data1'].quantile(0.9)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>data1</th>\n",
       "      <th>data2</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>key1</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>a</th>\n",
       "      <td>1.191629</td>\n",
       "      <td>5.052859</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>b</th>\n",
       "      <td>0.760298</td>\n",
       "      <td>1.443502</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "         data1     data2\n",
       "key1                    \n",
       "a     1.191629  5.052859\n",
       "b     0.760298  1.443502"
      ]
     },
     "execution_count": 43,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 笔记： 自定义聚合函数要比那些经过优化的函数慢得多\n",
    "#       这是因为在构造中间分组数据块时存在非常大的开销（函数调用、 数据重排等）\n",
    "\n",
    "# 如果要使用自己的聚合函数， 只需将其传入 aggregate 或 agg 方法即可：\n",
    "def peak_to_peak(arr):\n",
    "    return arr.max() - arr.min()\n",
    "\n",
    "grouped.agg(peak_to_peak)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead tr th {\n",
       "        text-align: left;\n",
       "    }\n",
       "\n",
       "    .dataframe thead tr:last-of-type th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr>\n",
       "      <th></th>\n",
       "      <th colspan=\"8\" halign=\"left\">data1</th>\n",
       "      <th colspan=\"8\" halign=\"left\">data2</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th></th>\n",
       "      <th>count</th>\n",
       "      <th>mean</th>\n",
       "      <th>std</th>\n",
       "      <th>min</th>\n",
       "      <th>25%</th>\n",
       "      <th>50%</th>\n",
       "      <th>75%</th>\n",
       "      <th>max</th>\n",
       "      <th>count</th>\n",
       "      <th>mean</th>\n",
       "      <th>std</th>\n",
       "      <th>min</th>\n",
       "      <th>25%</th>\n",
       "      <th>50%</th>\n",
       "      <th>75%</th>\n",
       "      <th>max</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>key1</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>a</th>\n",
       "      <td>3.0</td>\n",
       "      <td>0.488115</td>\n",
       "      <td>0.683655</td>\n",
       "      <td>0.085855</td>\n",
       "      <td>0.093431</td>\n",
       "      <td>0.101006</td>\n",
       "      <td>0.689245</td>\n",
       "      <td>1.277483</td>\n",
       "      <td>3.0</td>\n",
       "      <td>0.037377</td>\n",
       "      <td>2.537018</td>\n",
       "      <td>-2.622739</td>\n",
       "      <td>-1.158994</td>\n",
       "      <td>0.304751</td>\n",
       "      <td>1.367435</td>\n",
       "      <td>2.430120</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>b</th>\n",
       "      <td>2.0</td>\n",
       "      <td>0.470134</td>\n",
       "      <td>0.537612</td>\n",
       "      <td>0.089985</td>\n",
       "      <td>0.280060</td>\n",
       "      <td>0.470134</td>\n",
       "      <td>0.660209</td>\n",
       "      <td>0.850283</td>\n",
       "      <td>2.0</td>\n",
       "      <td>-0.170735</td>\n",
       "      <td>1.020710</td>\n",
       "      <td>-0.892486</td>\n",
       "      <td>-0.531611</td>\n",
       "      <td>-0.170735</td>\n",
       "      <td>0.190140</td>\n",
       "      <td>0.551016</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "     data1                                                              \\\n",
       "     count      mean       std       min       25%       50%       75%   \n",
       "key1                                                                     \n",
       "a      3.0  0.488115  0.683655  0.085855  0.093431  0.101006  0.689245   \n",
       "b      2.0  0.470134  0.537612  0.089985  0.280060  0.470134  0.660209   \n",
       "\n",
       "               data2                                                    \\\n",
       "           max count      mean       std       min       25%       50%   \n",
       "key1                                                                     \n",
       "a     1.277483   3.0  0.037377  2.537018 -2.622739 -1.158994  0.304751   \n",
       "b     0.850283   2.0 -0.170735  1.020710 -0.892486 -0.531611 -0.170735   \n",
       "\n",
       "                          \n",
       "           75%       max  \n",
       "key1                      \n",
       "a     1.367435  2.430120  \n",
       "b     0.190140  0.551016  "
      ]
     },
     "execution_count": 44,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 注意， 有些方法（如describe）也是可以用在这里的，即使严格来讲，它们并非聚合运算：\n",
    "grouped.describe()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>total_bill</th>\n",
       "      <th>tip</th>\n",
       "      <th>smoker</th>\n",
       "      <th>day</th>\n",
       "      <th>time</th>\n",
       "      <th>size</th>\n",
       "      <th>tip_pct</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>16.99</td>\n",
       "      <td>1.01</td>\n",
       "      <td>No</td>\n",
       "      <td>Sun</td>\n",
       "      <td>Dinner</td>\n",
       "      <td>2</td>\n",
       "      <td>0.059447</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>10.34</td>\n",
       "      <td>1.66</td>\n",
       "      <td>No</td>\n",
       "      <td>Sun</td>\n",
       "      <td>Dinner</td>\n",
       "      <td>3</td>\n",
       "      <td>0.160542</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>21.01</td>\n",
       "      <td>3.50</td>\n",
       "      <td>No</td>\n",
       "      <td>Sun</td>\n",
       "      <td>Dinner</td>\n",
       "      <td>3</td>\n",
       "      <td>0.166587</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>23.68</td>\n",
       "      <td>3.31</td>\n",
       "      <td>No</td>\n",
       "      <td>Sun</td>\n",
       "      <td>Dinner</td>\n",
       "      <td>2</td>\n",
       "      <td>0.139780</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>24.59</td>\n",
       "      <td>3.61</td>\n",
       "      <td>No</td>\n",
       "      <td>Sun</td>\n",
       "      <td>Dinner</td>\n",
       "      <td>4</td>\n",
       "      <td>0.146808</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>25.29</td>\n",
       "      <td>4.71</td>\n",
       "      <td>No</td>\n",
       "      <td>Sun</td>\n",
       "      <td>Dinner</td>\n",
       "      <td>4</td>\n",
       "      <td>0.186240</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   total_bill   tip smoker  day    time  size   tip_pct\n",
       "0       16.99  1.01     No  Sun  Dinner     2  0.059447\n",
       "1       10.34  1.66     No  Sun  Dinner     3  0.160542\n",
       "2       21.01  3.50     No  Sun  Dinner     3  0.166587\n",
       "3       23.68  3.31     No  Sun  Dinner     2  0.139780\n",
       "4       24.59  3.61     No  Sun  Dinner     4  0.146808\n",
       "5       25.29  4.71     No  Sun  Dinner     4  0.186240"
      ]
     },
     "execution_count": 45,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 面对列的多函数应用\n",
    "\n",
    "# 回到 小费 例子，\n",
    "# 导入 数据 后，添加一个小费百分比的列 tip_pct\n",
    "dataset_path = './../dataset/'\n",
    "tips = pd.read_csv(dataset_path + 'tips.csv')\n",
    "tips['tip_pct'] = tips['tip'] / tips['total_bill']\n",
    "tips[:6]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "day   smoker\n",
       "Fri   No        0.151650\n",
       "      Yes       0.174783\n",
       "Sat   No        0.158048\n",
       "      Yes       0.147906\n",
       "Sun   No        0.160113\n",
       "      Yes       0.187250\n",
       "Thur  No        0.160298\n",
       "      Yes       0.163863\n",
       "Name: tip_pct, dtype: float64"
      ]
     },
     "execution_count": 46,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 已经看到， 对 Series 或 DataFrame 列的聚合运算其实就是使用 aggregate（使用自定义函数） \n",
    "# 或调用诸如 mean、 std 之类的方法。\n",
    "# 可能希望对不同的列使用不同的聚合函数， 或一次应用多个函数,其实这也好办， 通过一些示例来进行讲解\n",
    "# 首先，根据 天 和 smoker 对 tips 进行分组：\n",
    "grouped = tips.groupby(['day', 'smoker'])\n",
    "\n",
    "grouped_pct = grouped['tip_pct']\n",
    "\n",
    "grouped_pct.agg('mean')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th>mean</th>\n",
       "      <th>std</th>\n",
       "      <th>peak_to_peak</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>day</th>\n",
       "      <th>smoker</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th rowspan=\"2\" valign=\"top\">Fri</th>\n",
       "      <th>No</th>\n",
       "      <td>0.151650</td>\n",
       "      <td>0.028123</td>\n",
       "      <td>0.067349</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Yes</th>\n",
       "      <td>0.174783</td>\n",
       "      <td>0.051293</td>\n",
       "      <td>0.159925</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th rowspan=\"2\" valign=\"top\">Sat</th>\n",
       "      <th>No</th>\n",
       "      <td>0.158048</td>\n",
       "      <td>0.039767</td>\n",
       "      <td>0.235193</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Yes</th>\n",
       "      <td>0.147906</td>\n",
       "      <td>0.061375</td>\n",
       "      <td>0.290095</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th rowspan=\"2\" valign=\"top\">Sun</th>\n",
       "      <th>No</th>\n",
       "      <td>0.160113</td>\n",
       "      <td>0.042347</td>\n",
       "      <td>0.193226</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Yes</th>\n",
       "      <td>0.187250</td>\n",
       "      <td>0.154134</td>\n",
       "      <td>0.644685</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th rowspan=\"2\" valign=\"top\">Thur</th>\n",
       "      <th>No</th>\n",
       "      <td>0.160298</td>\n",
       "      <td>0.038774</td>\n",
       "      <td>0.193350</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Yes</th>\n",
       "      <td>0.163863</td>\n",
       "      <td>0.039389</td>\n",
       "      <td>0.151240</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                 mean       std  peak_to_peak\n",
       "day  smoker                                  \n",
       "Fri  No      0.151650  0.028123      0.067349\n",
       "     Yes     0.174783  0.051293      0.159925\n",
       "Sat  No      0.158048  0.039767      0.235193\n",
       "     Yes     0.147906  0.061375      0.290095\n",
       "Sun  No      0.160113  0.042347      0.193226\n",
       "     Yes     0.187250  0.154134      0.644685\n",
       "Thur No      0.160298  0.038774      0.193350\n",
       "     Yes     0.163863  0.039389      0.151240"
      ]
     },
     "execution_count": 48,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 如果传入一组函数 或 函数名，得到的 DataFrame 的列就会以相应的函数命名：\n",
    "# 这里， 我们传递了一组聚合函数进行聚合， 独立对数据分组进行评估\n",
    "grouped_pct.agg(['mean', 'std', peak_to_peak])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th>foo</th>\n",
       "      <th>bar</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>day</th>\n",
       "      <th>smoker</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th rowspan=\"2\" valign=\"top\">Fri</th>\n",
       "      <th>No</th>\n",
       "      <td>0.151650</td>\n",
       "      <td>0.028123</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Yes</th>\n",
       "      <td>0.174783</td>\n",
       "      <td>0.051293</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th rowspan=\"2\" valign=\"top\">Sat</th>\n",
       "      <th>No</th>\n",
       "      <td>0.158048</td>\n",
       "      <td>0.039767</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Yes</th>\n",
       "      <td>0.147906</td>\n",
       "      <td>0.061375</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th rowspan=\"2\" valign=\"top\">Sun</th>\n",
       "      <th>No</th>\n",
       "      <td>0.160113</td>\n",
       "      <td>0.042347</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Yes</th>\n",
       "      <td>0.187250</td>\n",
       "      <td>0.154134</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th rowspan=\"2\" valign=\"top\">Thur</th>\n",
       "      <th>No</th>\n",
       "      <td>0.160298</td>\n",
       "      <td>0.038774</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Yes</th>\n",
       "      <td>0.163863</td>\n",
       "      <td>0.039389</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                  foo       bar\n",
       "day  smoker                    \n",
       "Fri  No      0.151650  0.028123\n",
       "     Yes     0.174783  0.051293\n",
       "Sat  No      0.158048  0.039767\n",
       "     Yes     0.147906  0.061375\n",
       "Sun  No      0.160113  0.042347\n",
       "     Yes     0.187250  0.154134\n",
       "Thur No      0.160298  0.038774\n",
       "     Yes     0.163863  0.039389"
      ]
     },
     "execution_count": 50,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 并非一定要接受 GroupBy 自动给出的那些列名， 特别是 lambda 函数， 它们的名称是 ''， \n",
    "#    这样的辨识度就很低了（通过函数的 name 属性看看就知道了）\n",
    "# 因此， 如果传入的是一个由 (name,function) 元组组成的列表，\n",
    "#    则各元组的第一个元素就会被用作 DataFrame 的列名（可以将这种二元元组列表看做一个有序映射） \n",
    "grouped_pct.agg([('foo', 'mean'), ('bar', np.std)])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "D:\\Anaconda\\lib\\site-packages\\ipykernel_launcher.py:7: FutureWarning: Indexing with multiple keys (implicitly converted to a tuple of keys) will be deprecated, use a list instead.\n",
      "  import sys\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead tr th {\n",
       "        text-align: left;\n",
       "    }\n",
       "\n",
       "    .dataframe thead tr:last-of-type th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th colspan=\"3\" halign=\"left\">tip_pct</th>\n",
       "      <th colspan=\"3\" halign=\"left\">total_bill</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th>count</th>\n",
       "      <th>mean</th>\n",
       "      <th>max</th>\n",
       "      <th>count</th>\n",
       "      <th>mean</th>\n",
       "      <th>max</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>day</th>\n",
       "      <th>smoker</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th rowspan=\"2\" valign=\"top\">Fri</th>\n",
       "      <th>No</th>\n",
       "      <td>4</td>\n",
       "      <td>0.151650</td>\n",
       "      <td>0.187735</td>\n",
       "      <td>4</td>\n",
       "      <td>18.420000</td>\n",
       "      <td>22.75</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Yes</th>\n",
       "      <td>15</td>\n",
       "      <td>0.174783</td>\n",
       "      <td>0.263480</td>\n",
       "      <td>15</td>\n",
       "      <td>16.813333</td>\n",
       "      <td>40.17</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th rowspan=\"2\" valign=\"top\">Sat</th>\n",
       "      <th>No</th>\n",
       "      <td>45</td>\n",
       "      <td>0.158048</td>\n",
       "      <td>0.291990</td>\n",
       "      <td>45</td>\n",
       "      <td>19.661778</td>\n",
       "      <td>48.33</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Yes</th>\n",
       "      <td>42</td>\n",
       "      <td>0.147906</td>\n",
       "      <td>0.325733</td>\n",
       "      <td>42</td>\n",
       "      <td>21.276667</td>\n",
       "      <td>50.81</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th rowspan=\"2\" valign=\"top\">Sun</th>\n",
       "      <th>No</th>\n",
       "      <td>57</td>\n",
       "      <td>0.160113</td>\n",
       "      <td>0.252672</td>\n",
       "      <td>57</td>\n",
       "      <td>20.506667</td>\n",
       "      <td>48.17</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Yes</th>\n",
       "      <td>19</td>\n",
       "      <td>0.187250</td>\n",
       "      <td>0.710345</td>\n",
       "      <td>19</td>\n",
       "      <td>24.120000</td>\n",
       "      <td>45.35</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th rowspan=\"2\" valign=\"top\">Thur</th>\n",
       "      <th>No</th>\n",
       "      <td>45</td>\n",
       "      <td>0.160298</td>\n",
       "      <td>0.266312</td>\n",
       "      <td>45</td>\n",
       "      <td>17.113111</td>\n",
       "      <td>41.19</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Yes</th>\n",
       "      <td>17</td>\n",
       "      <td>0.163863</td>\n",
       "      <td>0.241255</td>\n",
       "      <td>17</td>\n",
       "      <td>19.190588</td>\n",
       "      <td>43.11</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "            tip_pct                     total_bill                  \n",
       "              count      mean       max      count       mean    max\n",
       "day  smoker                                                         \n",
       "Fri  No           4  0.151650  0.187735          4  18.420000  22.75\n",
       "     Yes         15  0.174783  0.263480         15  16.813333  40.17\n",
       "Sat  No          45  0.158048  0.291990         45  19.661778  48.33\n",
       "     Yes         42  0.147906  0.325733         42  21.276667  50.81\n",
       "Sun  No          57  0.160113  0.252672         57  20.506667  48.17\n",
       "     Yes         19  0.187250  0.710345         19  24.120000  45.35\n",
       "Thur No          45  0.160298  0.266312         45  17.113111  41.19\n",
       "     Yes         17  0.163863  0.241255         17  19.190588  43.11"
      ]
     },
     "execution_count": 53,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 对于 DataFrame， 还有更多选择， \n",
    "# 可以定义一组应用于全部列的一组函数， 或不同的列应用不同的函数\n",
    "\n",
    "# 假设想要对 tip_pct 和 total_bill 列计算三个统计信息\n",
    "functions = ['count', 'mean', 'max']\n",
    "\n",
    "result = grouped['tip_pct', 'total_bill'].agg(functions)\n",
    "\n",
    "result"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th>count</th>\n",
       "      <th>mean</th>\n",
       "      <th>max</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>day</th>\n",
       "      <th>smoker</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th rowspan=\"2\" valign=\"top\">Fri</th>\n",
       "      <th>No</th>\n",
       "      <td>4</td>\n",
       "      <td>0.151650</td>\n",
       "      <td>0.187735</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Yes</th>\n",
       "      <td>15</td>\n",
       "      <td>0.174783</td>\n",
       "      <td>0.263480</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th rowspan=\"2\" valign=\"top\">Sat</th>\n",
       "      <th>No</th>\n",
       "      <td>45</td>\n",
       "      <td>0.158048</td>\n",
       "      <td>0.291990</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Yes</th>\n",
       "      <td>42</td>\n",
       "      <td>0.147906</td>\n",
       "      <td>0.325733</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th rowspan=\"2\" valign=\"top\">Sun</th>\n",
       "      <th>No</th>\n",
       "      <td>57</td>\n",
       "      <td>0.160113</td>\n",
       "      <td>0.252672</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Yes</th>\n",
       "      <td>19</td>\n",
       "      <td>0.187250</td>\n",
       "      <td>0.710345</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th rowspan=\"2\" valign=\"top\">Thur</th>\n",
       "      <th>No</th>\n",
       "      <td>45</td>\n",
       "      <td>0.160298</td>\n",
       "      <td>0.266312</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Yes</th>\n",
       "      <td>17</td>\n",
       "      <td>0.163863</td>\n",
       "      <td>0.241255</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "             count      mean       max\n",
       "day  smoker                           \n",
       "Fri  No          4  0.151650  0.187735\n",
       "     Yes        15  0.174783  0.263480\n",
       "Sat  No         45  0.158048  0.291990\n",
       "     Yes        42  0.147906  0.325733\n",
       "Sun  No         57  0.160113  0.252672\n",
       "     Yes        19  0.187250  0.710345\n",
       "Thur No         45  0.160298  0.266312\n",
       "     Yes        17  0.163863  0.241255"
      ]
     },
     "execution_count": 54,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 如你所见， 结果 DataFrame 拥有层次化的列， \n",
    "#           这相当于分别对各列进行聚合， 然后用 concat 将结果组装到一起， 使用列名用作 keys 参数\n",
    "result['tip_pct']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 55,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "D:\\Anaconda\\lib\\site-packages\\ipykernel_launcher.py:4: FutureWarning: Indexing with multiple keys (implicitly converted to a tuple of keys) will be deprecated, use a list instead.\n",
      "  after removing the cwd from sys.path.\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead tr th {\n",
       "        text-align: left;\n",
       "    }\n",
       "\n",
       "    .dataframe thead tr:last-of-type th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th colspan=\"2\" halign=\"left\">tip_pct</th>\n",
       "      <th colspan=\"2\" halign=\"left\">total_bill</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th>Durchschnitt</th>\n",
       "      <th>Abweichung</th>\n",
       "      <th>Durchschnitt</th>\n",
       "      <th>Abweichung</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>day</th>\n",
       "      <th>smoker</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th rowspan=\"2\" valign=\"top\">Fri</th>\n",
       "      <th>No</th>\n",
       "      <td>0.151650</td>\n",
       "      <td>0.000791</td>\n",
       "      <td>18.420000</td>\n",
       "      <td>25.596333</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Yes</th>\n",
       "      <td>0.174783</td>\n",
       "      <td>0.002631</td>\n",
       "      <td>16.813333</td>\n",
       "      <td>82.562438</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th rowspan=\"2\" valign=\"top\">Sat</th>\n",
       "      <th>No</th>\n",
       "      <td>0.158048</td>\n",
       "      <td>0.001581</td>\n",
       "      <td>19.661778</td>\n",
       "      <td>79.908965</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Yes</th>\n",
       "      <td>0.147906</td>\n",
       "      <td>0.003767</td>\n",
       "      <td>21.276667</td>\n",
       "      <td>101.387535</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th rowspan=\"2\" valign=\"top\">Sun</th>\n",
       "      <th>No</th>\n",
       "      <td>0.160113</td>\n",
       "      <td>0.001793</td>\n",
       "      <td>20.506667</td>\n",
       "      <td>66.099980</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Yes</th>\n",
       "      <td>0.187250</td>\n",
       "      <td>0.023757</td>\n",
       "      <td>24.120000</td>\n",
       "      <td>109.046044</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th rowspan=\"2\" valign=\"top\">Thur</th>\n",
       "      <th>No</th>\n",
       "      <td>0.160298</td>\n",
       "      <td>0.001503</td>\n",
       "      <td>17.113111</td>\n",
       "      <td>59.625081</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Yes</th>\n",
       "      <td>0.163863</td>\n",
       "      <td>0.001551</td>\n",
       "      <td>19.190588</td>\n",
       "      <td>69.808518</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                 tip_pct              total_bill            \n",
       "            Durchschnitt Abweichung Durchschnitt  Abweichung\n",
       "day  smoker                                                 \n",
       "Fri  No         0.151650   0.000791    18.420000   25.596333\n",
       "     Yes        0.174783   0.002631    16.813333   82.562438\n",
       "Sat  No         0.158048   0.001581    19.661778   79.908965\n",
       "     Yes        0.147906   0.003767    21.276667  101.387535\n",
       "Sun  No         0.160113   0.001793    20.506667   66.099980\n",
       "     Yes        0.187250   0.023757    24.120000  109.046044\n",
       "Thur No         0.160298   0.001503    17.113111   59.625081\n",
       "     Yes        0.163863   0.001551    19.190588   69.808518"
      ]
     },
     "execution_count": 55,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 跟前面一样， 这里也可以传入带有自定义名称的一组元组：\n",
    "ftuples = [('Durchschnitt', 'mean'),('Abweichung', np.var)]\n",
    "\n",
    "grouped['tip_pct', 'total_bill'].agg(ftuples)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th>tip</th>\n",
       "      <th>size</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>day</th>\n",
       "      <th>smoker</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th rowspan=\"2\" valign=\"top\">Fri</th>\n",
       "      <th>No</th>\n",
       "      <td>3.50</td>\n",
       "      <td>9</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Yes</th>\n",
       "      <td>4.73</td>\n",
       "      <td>31</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th rowspan=\"2\" valign=\"top\">Sat</th>\n",
       "      <th>No</th>\n",
       "      <td>9.00</td>\n",
       "      <td>115</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Yes</th>\n",
       "      <td>10.00</td>\n",
       "      <td>104</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th rowspan=\"2\" valign=\"top\">Sun</th>\n",
       "      <th>No</th>\n",
       "      <td>6.00</td>\n",
       "      <td>167</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Yes</th>\n",
       "      <td>6.50</td>\n",
       "      <td>49</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th rowspan=\"2\" valign=\"top\">Thur</th>\n",
       "      <th>No</th>\n",
       "      <td>6.70</td>\n",
       "      <td>112</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Yes</th>\n",
       "      <td>5.00</td>\n",
       "      <td>40</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "               tip  size\n",
       "day  smoker             \n",
       "Fri  No       3.50     9\n",
       "     Yes      4.73    31\n",
       "Sat  No       9.00   115\n",
       "     Yes     10.00   104\n",
       "Sun  No       6.00   167\n",
       "     Yes      6.50    49\n",
       "Thur No       6.70   112\n",
       "     Yes      5.00    40"
      ]
     },
     "execution_count": 56,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 现在， 假设想要对一个列或不同的列应用不同的函数\n",
    "#  具体的办法是向 agg 传入一个从列名映射到函数的字典：\n",
    "grouped.agg({'tip' : np.max, 'size' : 'sum'})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead tr th {\n",
       "        text-align: left;\n",
       "    }\n",
       "\n",
       "    .dataframe thead tr:last-of-type th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th colspan=\"4\" halign=\"left\">tip_pct</th>\n",
       "      <th>size</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th>min</th>\n",
       "      <th>max</th>\n",
       "      <th>mean</th>\n",
       "      <th>std</th>\n",
       "      <th>sum</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>day</th>\n",
       "      <th>smoker</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th rowspan=\"2\" valign=\"top\">Fri</th>\n",
       "      <th>No</th>\n",
       "      <td>0.120385</td>\n",
       "      <td>0.187735</td>\n",
       "      <td>0.151650</td>\n",
       "      <td>0.028123</td>\n",
       "      <td>9</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Yes</th>\n",
       "      <td>0.103555</td>\n",
       "      <td>0.263480</td>\n",
       "      <td>0.174783</td>\n",
       "      <td>0.051293</td>\n",
       "      <td>31</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th rowspan=\"2\" valign=\"top\">Sat</th>\n",
       "      <th>No</th>\n",
       "      <td>0.056797</td>\n",
       "      <td>0.291990</td>\n",
       "      <td>0.158048</td>\n",
       "      <td>0.039767</td>\n",
       "      <td>115</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Yes</th>\n",
       "      <td>0.035638</td>\n",
       "      <td>0.325733</td>\n",
       "      <td>0.147906</td>\n",
       "      <td>0.061375</td>\n",
       "      <td>104</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th rowspan=\"2\" valign=\"top\">Sun</th>\n",
       "      <th>No</th>\n",
       "      <td>0.059447</td>\n",
       "      <td>0.252672</td>\n",
       "      <td>0.160113</td>\n",
       "      <td>0.042347</td>\n",
       "      <td>167</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Yes</th>\n",
       "      <td>0.065660</td>\n",
       "      <td>0.710345</td>\n",
       "      <td>0.187250</td>\n",
       "      <td>0.154134</td>\n",
       "      <td>49</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th rowspan=\"2\" valign=\"top\">Thur</th>\n",
       "      <th>No</th>\n",
       "      <td>0.072961</td>\n",
       "      <td>0.266312</td>\n",
       "      <td>0.160298</td>\n",
       "      <td>0.038774</td>\n",
       "      <td>112</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Yes</th>\n",
       "      <td>0.090014</td>\n",
       "      <td>0.241255</td>\n",
       "      <td>0.163863</td>\n",
       "      <td>0.039389</td>\n",
       "      <td>40</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "              tip_pct                               size\n",
       "                  min       max      mean       std  sum\n",
       "day  smoker                                             \n",
       "Fri  No      0.120385  0.187735  0.151650  0.028123    9\n",
       "     Yes     0.103555  0.263480  0.174783  0.051293   31\n",
       "Sat  No      0.056797  0.291990  0.158048  0.039767  115\n",
       "     Yes     0.035638  0.325733  0.147906  0.061375  104\n",
       "Sun  No      0.059447  0.252672  0.160113  0.042347  167\n",
       "     Yes     0.065660  0.710345  0.187250  0.154134   49\n",
       "Thur No      0.072961  0.266312  0.160298  0.038774  112\n",
       "     Yes     0.090014  0.241255  0.163863  0.039389   40"
      ]
     },
     "execution_count": 57,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 只有将多个函数应用到至少一列时， DataFrame才会拥有层次化的列\n",
    "grouped.agg({'tip_pct' : ['min', 'max', 'mean', 'std'], 'size' : 'sum'})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
